#ifndef __YHM_CLIENT_H__
#define __YHM_CLIENT_H__

#include <infiniband/verbs.h>
#include <queue>
#include <atomic>
#include <mutex>
#include <pthread.h>
#include <algorithm>
#include <cmath>

#define SHORT_STR_LEN 32
#define p_info(fmt, ...) printf("CLIENT::INFO: " fmt, ##__VA_ARGS__);
#define p_err(fmt, ...) fprintf(stderr, "CLIENT::ERR: " fmt, ##__VA_ARGS__);
#define p_die(fmt, ...) {fprintf(stderr, "CLIENT::DIE: " fmt, ##__VA_ARGS__); assert(0);}
#define UNUSED(x) ((void)(x))
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)<(y)?(x):(y))
struct qp_info{
  int lid;
  int qpn;
};  

struct client_shared_ctx {
  int ref; //reference cnt, how many thread point
  //memcache info
  char mc_ip[SHORT_STR_LEN];
  int mc_port;
  struct mc_ctx *mi;

  //base info
  int ib_port;
  int server_num;
  int id;
  long cache_size;
  
  //rdma context
  struct ibv_context *ctx;
  //port attribute
  struct ibv_port_attr port_attr;
  //protection area
  struct ibv_pd *pd;

  //all qp of client
  struct ibv_qp **client_qp;
  struct ibv_cq **send_cq;
  struct ibv_cq *recv_cq;

  //server qp_info
  struct qp_info *qp_info;
  
  //send request
  std::queue<int> *send_id;
  std::mutex *send_id_lock;
};
struct client_thread_ctx{
  struct client_shared_ctx *sctx;

  // for send use
  union req_union *req;
  struct ibv_mr *req_mr;

  void *page_buf;
  struct ibv_mr *page_mr;
};
/*
  使用这个初始化一个全局上下文
*/
struct client_thread_ctx *api_main_thread_init(int argc, char *argv[]);
/*
  使用这个来创建一个线程上下文
*/
typedef struct Addr{
  union{
    unsigned long val;
    struct {
      unsigned long offset : 48;
      unsigned long region_id : 16;
    };
  };
} Addr;
struct client_thread_ctx *api_new_thread_init(struct client_thread_ctx *ctx);
/*
  创建一个内存池
*/
Addr api_alloc_dsm(struct client_thread_ctx *ctx, const char *name, long size);
#endif